package com.yayun.merchant.websocket;

import com.alibaba.fastjson2.JSON;
import com.yayun.common.core.domain.model.LoginUser;
import com.yayun.common.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint("/websocket/auction/{auctionId}")
@Component
public class AuctionWebSocket {
    private static final Logger log = LoggerFactory.getLogger(AuctionWebSocket.class);

    /**
     * 存放每个拍卖的在线会话
     */
    private static final Map<String, Map<String, Session>> auctionSessions = new ConcurrentHashMap<>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("auctionId") String auctionId) {
        // 获取当前用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser != null) {
            String userId = loginUser.getUserId().toString();
            // 存储会话
            auctionSessions.computeIfAbsent(auctionId, k -> new ConcurrentHashMap<>())
                    .put(userId, session);
            log.info("用户{}加入拍卖{}的WebSocket连接", userId, auctionId);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("auctionId") String auctionId) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser != null) {
            String userId = loginUser.getUserId().toString();
            // 移除会话
            Map<String, Session> sessions = auctionSessions.get(auctionId);
            if (sessions != null) {
                sessions.remove(userId);
                if (sessions.isEmpty()) {
                    auctionSessions.remove(auctionId);
                }
            }
            log.info("用户{}退出拍卖{}的WebSocket连接", userId, auctionId);
        }
    }

    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到客户端消息:{}", message);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket发生错误：{}", error.getMessage());
        // 尝试关闭异常的连接
        try {
            if (session.isOpen()) {
                session.close();
            }
        } catch (Exception e) {
            log.error("关闭WebSocket连接失败：{}", e.getMessage());
        }
        
        // 清理会话映射
        for (Map<String, Session> sessions : auctionSessions.values()) {
            sessions.values().removeIf(s -> s.getId().equals(session.getId()));
        }
        // 清理空的拍卖会话
        auctionSessions.entrySet().removeIf(entry -> entry.getValue().isEmpty());
    }

    /**
     * 发送消息给指定拍卖的所有用户
     */
    public static void sendMessage(String auctionId, Object message) {
        Map<String, Session> sessions = auctionSessions.get(auctionId);
        if (sessions != null && !sessions.isEmpty()) {
            String messageText = JSON.toJSONString(message);
            sessions.values().forEach(session -> {
                try {
                    if (session.isOpen()) {
                        session.getBasicRemote().sendText(messageText);
                    } else {
                        // 移除已关闭的会话
                        sessions.values().removeIf(s -> s.getId().equals(session.getId()));
                    }
                } catch (Exception e) {
                    log.error("发送WebSocket消息失败：{}", e.getMessage());
                    try {
                        session.close();
                    } catch (Exception ex) {
                        log.error("关闭失效的WebSocket连接失败：{}", ex.getMessage());
                    }
                }
            });
            
            // 如果所有会话都已关闭，清理该拍卖的会话映射
            if (sessions.isEmpty()) {
                auctionSessions.remove(auctionId);
            }
        }
    }

    /**
     * 发送消息给指定用户
     */
    public static void sendMessageToUser(String auctionId, String userId, Object message) {
        Map<String, Session> sessions = auctionSessions.get(auctionId);
        if (sessions != null) {
            Session session = sessions.get(userId);
            if (session != null) {
                try {
                    session.getBasicRemote().sendText(JSON.toJSONString(message));
                } catch (Exception e) {
                    log.error("发送WebSocket消息失败：{}", e.getMessage());
                }
            }
        }
    }
} 